<?php
/**
 * 分页类
 * */

define("pager","1");
//Lwgpageturn ==> pager,最后修改,xuleit@126.com 2011.4.24 07:29
class mypager {
	//----------可以设置值的变量----------------------------------------
	public $pageSize;//每页显示数
	public $maxPageSize=100;  //每页最多显示数,用来规定$pageSize不能超过$maxPageSize
	public $sql;//sql语句
	public $navchar=array('首页','[<]','[>]','末页','','');
	//public $navchar=array('[<<]','[<]','[>]','[>>]','[<<]','[>>]');
	//导航条的显示字符，值可以自定义，如一个img标签
	//$navchar[0]表示第一页，$navchar[1]表示前一页，$navchar[2]表示后一页，$navchar[3]表示最后页，$navchar[4]表示前n页,$navchar[5]表示后n页
	private $key;//如果一个页面中有多个分页时作为区别标记
	public $debug=true;//是否显示调试信息

	//----------用来获取值的变量---------------------------------------
	public $totalNum;//总记录数
	public $totalPage;//总页数
	public $startNum;//本页的第一条在总数中的序数
	public $endNum;//本页的最后一条在总数中的序数
	public $pageNum;//本页在总页数中的序数
	public $f;//结果记录的集合
	public $id;//每条记录的序号
	public $linkhead;//链接指定的url及要传递的相关参数
	public $err;//记录最后一条错误信息
	public $result;//记录当页的sql查询出来的结果数组
	public $params ; //记录需要传递的变量

	/**
	 * @  $pageSize 每页显示的数量
	 * @  $key 当前分页的标记,如果页面有多个分页，需要用到
	 * @  $cachetime 缓存时间
	 * @  $params 除了分页相关的变量，还需要传输的变量，例如keyword等
	 * */
	function __construct($sql,$paramNames=array(),$pageSize="",$key="",$cachetime=0){
		$this->sql = $sql;
		$this->pageSize=$pageSize;
		$this->key=$key;
		$this->cachetime=$cachetime;
		$this->params = $paramNames;
	}

	public function setPageSize($pageSize){
		$this->pageSize = $pageSize;
	}

	/**
	 * 返回result數組
	 * */
	public function getResult(){
		$this->run($this->sql);
		return $this->result;
	}

	/**
	 * 运行sql命令
 	* */
	function run($sql='',$db=''){
		if($db==''){
			$db = db();
		}


		if ($sql!="")$this->sql=$sql;
		if ($this->sql=="") return $this->output("错误:未给出sql查询语句!");
		if ($this->pageSize<=0) {
			$this->pageSize=10;
			if(IS_ADMIN_SYS) $this->pageSize = 10;
		}
		$querystring = '';//传递过来的参数字窜
		$ispost=false;//是否有$_POST变量,如果有的话,则在翻页时只传递其值,其它的一律省略

		if (myrequest::isPost()){//将$_POST变量的键值作为翻页时传递的参数
			$formlink = "";
			$ispost=true;
			foreach ($_POST as $key => $value) {
				//循环分析出$_POST变量的键值
				//if (!empty($value)) $formlink .=$key.",".rawurlencode($value).",";//@todo
			}
			$querystring=$formlink;
		}//@todo remove under line
		else {//如果没有$_POST变量,则将$_GET变量分析后作为翻页时传递的参数
			$qs=explode("totalNum".$this->key,myrequest::getPhpSelf());
			if ($qs[0]!="")$querystring=(substr($qs[0],-1)=="&")?$qs[0]:$qs[0]."&";
			//扔掉totalNum及其以后的参数,因为要付新的值
		}


		//巨型表查询优化
		$reg = "/SELECT.*?\s+FROM\s+(.*)/i";
		$find = preg_match($reg,$sql,$matches);
		if($find){
			$countSql = 'SELECT COUNT(*) AS NUM FROM '.$matches[1];
			$regHaveLimit = "/(.*?)\s+ORDER\s+(.*?)\s+LIMIT\s+(.*)/i";
			$regNoLimit = "/(.*?)\s+ORDER\s+/i";
			$findHaveLimit = preg_match($regHaveLimit,$countSql,$matches);
			if($findHaveLimit){
				$noOrderSql = $matches[1].' LIMIT '.$matches[3];
			}else if(preg_match($regNoLimit,$countSql,$matches)){
				$noOrderSql = $matches[1];
			}else{
				$noOrderSql = $countSql;
			}
			$result = $db->cacheQuery($countSql,'','',$this->cachetime);
			$this->totalNum = $result[0]['NUM'];
		}


		//每页显示多少条记录
		$pSize = intval(g("pageSize".$this->key));
		if ($pSize>0){
			if($pSize > $this->maxPageSize){
				$this->pageSize = $this->maxPageSize;
			}else{
				$this->pageSize = $pSize;
			}
		}

		$this->totalPage=ceil($this->totalNum/$this->pageSize);//总页数

		//当前页码
		$pNum = intval(g("pageNum".$this->key));
		if($ispost || $pNum < 1){
			$this->pageNum = 1;
		}else {
			$this->pageNum = $pNum;
		}
		//当前页码最大不超过totalPage
		if ($this->pageNum>$this->totalPage){
			$this->pageNum=$this->totalPage;
		}

		$this->startNum = max(($this->pageNum-1) * $this->pageSize,0);
		
		
		$this->endNum=min($this->startNum+$this->pageSize,$this->totalNum);

		//设置limit,使结果为本页需要显示的记录
		if (preg_match("/limit(\s+)/si",$sql,$regs)){ $this->output('sql语句中不能含有limit'); }
		$limitedSql  = sprintf("%s LIMIT %d, %d", $this->sql, $this->startNum,$this->pageSize);
		//echo 	$limitedSql;
		$this->result = $db->cacheQuery($limitedSql,'','',$this->cachetime);
		$this->linkhead = g('con').','.g('act').'?';
		foreach ($this->params as $key){
			$this->linkhead .= '&'.$key.'='.urlencode($_GET[$key]);
		}
		//print_R($this->params);

	}

	//显示如"共14页27条"
	//使用方法:echo $pagerObj->total()
	function total(){
		if ($this->pageSize=="")return;
		return "总".$this->totalNum."项 共".$this->totalPage."页";
	}

	//显示如"本页从第9条到第10条"
	//使用方法:echo $pagerObj->fromto()
	function fromto(){
		if ($this->pageSize=="")return;
		$startNum=$this->startNum+1;
		if ($this->totalNum==0)$startNum=0;
		return "本页从第".$startNum."条到第".$this->endNum."条";
	}
	
	
	function show (){
		return $this->p();
	}
	

	//navbar方法显示页数导航条
	//$num_size表示多少个导航数字,如$num_size=5则显示" 1 2 3 4 5 "
	//$num_style为数字导航条的风格,
	//当$num_style的值为1时将数字分组,显示如"前5页 前1页 1 2 3 4 5 后一页 后5页";
	//当$num_style的值为非1时,显示如" 1 2 3 4 5 …";
	//$nolink_show没有链接的导航字符是否显示，true显示，false不显示
	//$nolink_color没有链接的导航字符显示的颜色
	//使用方法：echo $pagerObj->navbar(10,2，false,"#ffff00")
	function navbar($num_size=10,$num_style=1,$nolink_show=true,$nolink_color="#ff0000"){
		if ($this->totalPage<=1)return;
		$thisunit = '';
		$preunit  = '';
		$nextunit = '';
		$startpage= '';
		$endpage  = '';
		$str_preunit = '';
		$str_nextunit= '';
		$str_frontell = '';
		$str_backell  = '';
		$str_num = '';

		if ($num_size>0){
			if ($num_style==1){
				$thisunit=ceil($this->pageNum/$num_size);//取得本页所有的组
				$preunit=($thisunit>1)?($thisunit-1):"";//取得上页所有的组
				$nextunit=($thisunit<ceil($this->totalPage/$num_size))?($thisunit+1):"";//取得下页所有的组
				$startpage=($thisunit-1)*$num_size+1;//取得本组的开始页
				$endpage=min($thisunit*$num_size,$this->totalPage);//取得本组的最后页
				if ($preunit!=""){
					$str_preunit=" <a href=\"".$this->linkhead."&pageNum".$this->key."=".(($thisunit-2)*$num_size+1)."\" title=\"前".$num_size."页\">".$this->navchar[4]."</a> ";
				}
				if ($nextunit!=""){
					$str_nextunit=" <a href=\"".$this->linkhead."&pageNum".$this->key."=".($thisunit*$num_size+1)."\" title=\"后".$num_size."页\">".$this->navchar[5]."</a>";
				}
			}
			else {
				$tmpnum=ceil($num_size/2);
				$startpage=max(min($this->pageNum-$tmpnum,$this->totalPage-$num_size+1),1);
				$endpage=min($startpage+$num_size-1,$this->totalPage);
				if ($startpage>1)$str_frontell=" … ";
				if ($endpage<$this->totalPage)$str_backell=" … ";
			}
			$str_num="";
			for ($i=$startpage;$i<=$endpage;$i++){
				if ($i==$this->pageNum)$str_num.=" <font color=\"".$nolink_color."\">第".$i."页</font> ";
				else $str_num.= " <a href=\"".$this->linkhead."&pageNum".$this->key."=".$i."\" title=\"第".$i."页\">[".$i."]</a> ";
			}
		}

		$str_first = '';
		$str_pre   = '';
		$str_next  = '';
		$str_last  = '';

		
		if ($this->pageNum > 1){
			$str_first=" <a href=\"".$this->linkhead."&pageNum".$this->key."=1\" title=\"第一页\" target=_self>".$this->navchar[0]."</a>  ";
			$str_pre=" <a href=\"".$this->linkhead."&pageNum".$this->key."=".($this->pageNum-1)."\" title=\"前一页\" target=_self>".$this->navchar[1]."</a> ";
		}
		else if ($nolink_show){
			$str_first=" <font color=\"".$nolink_color."\">".$this->navchar[0]."</font> ";
			$str_pre=" <font color=\"".$nolink_color."\">".$this->navchar[1]."</font> ";
		}

		if ($this->pageNum<$this->totalPage){
			$str_next= " <a href=\"".$this->linkhead."&pageNum".$this->key."=".($this->pageNum+1)."\" title=\"后一页\" target=_self>".$this->navchar[2]."</a> ";
			$str_last= " <a href=\"".$this->linkhead."&pageNum".$this->key."=".$this->totalPage."\" title=\"最后页\" target=_self>".$this->navchar[3]."</a> 　";
		}
		else if ($nolink_show){
			$str_next=" <font color=\"".$nolink_color."\">".$this->navchar[2]."</font> ";
			$str_last=" <font color=\"".$nolink_color."\">".$this->navchar[3]."</font> ";
		}
		//echo '$this->pageNum='.$this->pageNum.$str_first;
		return $str_first.$str_preunit.$str_pre.$str_frontell.$str_num.$str_backell.$str_next.$str_nextunit.$str_last;
	}

	//用下拉列表显示如"到第n页共m页"
	//使用方法:echo $pagerObj->pagejump()
	function pagejump(){
		if ($this->totalPage<=1)return;
		$options=array();
		for ($i=1;$i<=$this->totalPage;$i++)$options[$i]=$i;
		return "到第".$this->droplist("pageNum".$this->key,$options)."页/共".$this->totalPage."页";
	}

	//用下拉列表显示如"每页显示n条 "
	//使用方法:echo $pagerObj->pageSize()
	function pageSize(){
		if ($this->pageSize=="")return;
		$options=array('1'=>'1','2'=>'2','3'=>'3','4'=>'4','6'=>'6','8'=>'8','9'=>'9','10'=>'10','20'=>'20','30'=>'30','50'=>'50','100'=>'100','全部'=>$this->totalNum);
		$str="";
		return "每页显示".$this->droplist("pageSize".$this->key,$options)."条";
	}

	//droplist()用来生成下拉选单
	function droplist($name,$options,$class=""){
		$write="";
		$write.="<select name='".$name."' ";
		if ($class!="")$write.="class='".$class."' ";
		$write.="onchange='java script:location.href=this.options[this.selectedIndex].value;'>";
		$tmplinkhead=preg_replace("&/pageSize".$this->key."=[0-9]*/i","",$this->linkhead);
		$preval=0;
		while ( list( $key, $val ) = each( $options ) ) {
			if ($name=="pageSize".$this->key){
				if ($val!=$this->totalNum){
					$pageNum=ceil($this->pageNum*$this->pageSize/$val);
					while (($pageNum-1)*$val>$this->startNum)$pageNum-=1;
					//由于每页显示记录数改变了,所以要重新计算$pageNum
					$linkhead=$tmplinkhead."&pageNum".$this->key."=".max($pageNum,1);
				}
				else $linkhead=$this->linkhead;

				if ($this->maxPageSize>0 && $this->totalNum>$this->maxPageSize){
					if ($val>=$this->maxPageSize){
						$write.="<option value=".$linkhead."&".$name."=".$this->maxPageSize.(($this->maxPageSize==$this->pageSize)?" selected >":">").$this->maxPageSize."</option>";
						//创建值为$this->pageSize的选单
						break;
					}
				}
				else if ($preval<$this->pageSize && $val>$this->pageSize)$write.="<option value=".$linkhead."&".$name."=".$this->pageSize." selected>".$this->pageSize."</option>";
				//当$pageSize的值不在选单中时则创建它

				$write.="<option value=".$linkhead."&".$name."=".$val;
				if ($this->pageSize==$val)$write.=" selected";
				$preval=$val;
			}
			else if ($name=="pageNum".$this->key){
				$write.="<option value=".$this->linkhead."&".$name."=".$val;
				if ($this->pageNum==$val)$write.=" selected";
			}
			$write.=">".$key."</option>";
		}//end while
		$write.="</select>";
		return $write;
	}

	//生成到第几页的表单,xuleit@126.com
	//使用的时候注意一定要将该代码放在其他表单之外，否则，本功能是不能用的。
	function inputpage($name='',$class=""){
		$write="";
		$write.="<form style='margin:0' name='".$name."' ";
		if ($class!="")$write.="class='".$class."' ";
		$write.=" onsubmit='return false' action='' method='post'>";
		$write.="<script>function gopage$this->key(f){
         window.location = f.linkhead.value+'&pageNum$this->key='+f.pageNum$this->key.value;
         return false;
        }</script>";
		$write .= "跳转到第<input size='2' type=text name=pageNum$this->key value=\"$this->pageNum\"><input type=hidden name=linkhead value=\"$this->linkhead\">页<input type=button value='GO' onclick='gopage$this->key(this.form)'></form>";
		return $write;
	}

	//输出错误信息
	function output($msg){
		if ($msg!="")$this->err=$msg;
		if ($this->debug)echo "<script language=\"JavaScript\" type=\"text/JavaScript\">alert('".$msg."');history.go(-1)</script>";
		return false;
	}

	//打印一个普通的分页
	function p()
	{
		echo '<table width=100% border=0 cellspacing=0 cellpadding=0 class="table table-hover text-center"><tr valign=bottom><td align=right width=50% >';
		echo $this->total().' ';
		echo $this->navbar(1,1,true,'#FF0000');
		echo ' </td><td width=6></td><td align=left><div class="pageList">';
		echo $this->inputpage();
		echo '</div></td></tr></table>';
	}
	


	/**
	 * 返回结果列表
	 * @param Bool $isShowFieldname 是否显示字段名称
	 * @param Array $fieldCallFun 字段显示的时候调用对应函数,注意不用函数返回<li>，只需要返回<li></li>里边的内容
	 * @param String $primaryField 主键或者能够标识该行数据的值对应的字段
	 * @param Array $skipFields 跳过不显示的字段  
	 * */
	function  getList($isShowFieldname=true,$fieldCallFun=array(),$primaryField='',$skipFields=array()){
		$returnStr = '';
		$returnStr .= "<div class=\"wrapper clearfix\">\r\n<div class=\"plist\"><dl>";
		if($this->sql == ''){
			die('plz $pager->run($sql) first!');
		}

		//----获取字段名称------
		if(!empty($this->result[0])){//begin main if
			$keys   = array_keys($this->result[0]);
			$fields = array();
			$returnStr .= '<dd>';
			foreach ($keys as $k){
				if(!is_int($k)){
					$fields[] = $k;
					if(!in_array($k,$skipFields)){//跳过不显示的字段
						$returnStr .= "<li class=\"pr\">$k</li>";
					}
				}
			}
			$returnStr .= "</dd>\r\n";

			//-----获取具体结果----------
			$numF = count($fields); //字段数量
			$num = count($this->result);
			for ($i = 0; $i < $num; $i++){
				$returnStr .= '<dd>';
				for ($j = 0; $j < $numF;$j++){
					$fieldName = $fields[$j];
					$show = $fieldValue = $this->result[$i][$fieldName];
					if(key_exists($fieldName,$fieldCallFun)){//哪些字段显示的时候，需要调用函数的
						$primaryValue = $this->result[$i][$primaryField];
						$show = $fieldCallFun[$fieldName]($fieldValue,$primaryValue);
					}

					$currentField = $fields[$j];
					if(!in_array($currentField,$skipFields)){//跳过不显示字段
						if($j  != $numF-1 ){//不是最后一个字段
							$returnStr .= "<li class=\"pr\">&nbsp;{$show}</li>";
						}else{//最后一个字段
							$returnStr .= "<li>{$show}</li>";
						}
					}
				}//end sub for
				$returnStr .= "</dd>\r\n";
			}//end main for
		}else {//end main if
			$returnStr .= "<dd><li class=\"pr\">暂无数据</li></dd>";
		}
		$returnStr .= '</dl></div>';

		//----获取分页字串-------------
		$returnStr .= "<div class=\"wrapper clearfix\">\r\n".self::navbar().'</div>';
		return $returnStr;
	}

}

//---------使用方法----------------------------------------------
/*
$cmpny_c='P30719';
$kindc='CAA';
$typec='ETC';
$codec='PALMONE02';
$cmpny='P30719';
$price='￥1,550';

$sql="select a.kind_c as kind_c, a.prod_c as prod_c ,
a.type_c as type_c ,
a.name_n as name_n ,
x.price_q  as price_q ,
a.prod_cmpny_n as prod_cmpny_n ,
y.desc_m as codedesc_m ,
y.name_n as codename_n,
a.image_l as image_l,
a.image_s as image_s
from  tcmdt x  , tproduct a  ,tcode y
where x.cmpny_c='$cmpny_c'
and x.kind_c = a.kind_c
and x.type_c = a.type_c
and x.prod_c = a.prod_c
and x.price_q > 0
and a.kind_c = y.kind_c
and y.type_c = 'tp'
and a.type_c = y.code_c
order by y.seq_q,a.type_c,a.prod_cmpny_n, a.name_n";

$searchKeyword = array();
$pageSize = 2;
$pagerKey = 1;//辨识同一页面多个分页组件
$pagerObj=new mypager($sql,$searchKeyword,2,1);
$pagerObj->show();//显示一个简单的分页
print_R($pagerObj->getResult());//当前的结果

//下面单列显示记录示例
for ($i=0;$i<($pagerObj->endNum-$pagerObj->startNum);$i++){
echo $pagerObj->id[$i];//显示序号
echo $pagerObj->f[$i]['name_n']."<br>";//显示字段名为name的第$i条记录
}
echo $pagerObj->total();
echo $pagerObj->navbar(10,2,false,'#FF0000');

//下面多列显示记录示例
echo "<table>";
$colnum=2;//表示分两列
$totalraw=ceil(($pagerObj->endNum-$pagerObj->startNum)/$colnum);
for ($x=0;$x<$totalraw;$x++){
echo "<tr>";
$startsell=$colnum*$x;
$endsell=min($x*$colnum+$colnum,$pagerObj->endNum-$pagerObj->startNum);
for ($i=$startsell;$i<$endsell;$i++){
echo "<td>";
echo $pagerObj->id[$i];//显示序号
echo $pagerObj->f[$i]['name_n']."<br>";//显示字段名为name的第$i条记录
echo "</td>";
}
echo "</tr>";
}
echo "</table>";
*/



?>